/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2020 Google LLC.
 */
#include <linux/tpuv1_ioctl.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include "tpu_common.h"
#include "tpuv1_core.h"
#include "../../gasket/gasket_core.h"
static int __init tpuv2_init(void);
static void tpuv2_exit(void);
#define TPUV2_DRIVER_VERSION "1.0.0"
#define TPUV2_PCI_SUBSYSTEM_DEVICE_ID 0x004F
enum tpuv2_bar2_regs {
 TPUV2_BAR2_REG_TN0_BC_HOST_INT_INTVECCTL = 0x0800090,
 TPUV2_BAR2_REG_TN1_BC_HOST_INT_INTVECCTL = 0x1800090,
};
static const struct pci_device_id tpuv2_pci_ids[] = {
 { PCI_DEVICE_SUB(TPUV1_PCI_VENDOR_ID, TPUV1_PCI_DEVICE_ID, PCI_ANY_ID,
  TPUV2_PCI_SUBSYSTEM_DEVICE_ID) }, { 0 }
};
struct legacy_gasket_interrupt_desc tpuv2_interrupts[] = {
 { TPUV1_INTERRUPT_TN0_HBM_WRITE_QUEUE,
  TPUV1_BAR2_REG_TN0_HBM_WRITE_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_NF_DESCRIPTOR_QUEUE,
  TPUV1_BAR2_REG_TN0_NF_DESCRIPTOR_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_CHIP_DEBUG_QUEUE,
  TPUV1_BAR2_REG_TN0_CHIP_DEBUG_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_TC_INFEED_QUEUE,
  TPUV1_BAR2_REG_TN0_TC_INFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_BC_INFEED_QUEUE,
  TPUV1_BAR2_REG_TN0_BC_INFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_TC_OUTFEED_QUEUE,
  TPUV1_BAR2_REG_TN0_TC_OUTFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_BC_OUTFEED_QUEUE,
  TPUV1_BAR2_REG_TN0_BC_OUTFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_BC_FSM_MICROCODE_QUEUE,
  TPUV1_BAR2_REG_TN0_FSM_MICROCODE_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_NF_OUTFEED_QUEUE,
  TPUV1_BAR2_REG_TN0_NF_OUTFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN0_TC_HOST_0, TPUV1_BAR2_REG_TN0_TC_HOST_INT_INTVECCTL,
  PACK_0 },
 { TPUV1_INTERRUPT_TN0_TC_HOST_1, TPUV1_BAR2_REG_TN0_TC_HOST_INT_INTVECCTL,
  PACK_1 },
 { TPUV1_INTERRUPT_TN0_TC_HOST_2, TPUV1_BAR2_REG_TN0_TC_HOST_INT_INTVECCTL,
  PACK_2 },
 { TPUV1_INTERRUPT_TN0_TC_HOST_3, TPUV1_BAR2_REG_TN0_TC_HOST_INT_INTVECCTL,
  PACK_3 },
 { TPUV1_INTERRUPT_TN0_TC_HALTED, TPUV1_BAR2_REG_TN0_TC_HALTED_INTVECCTL,
  UNPACKED },
 { TPUV1_INTERRUPT_TN1_HBM_WRITE_QUEUE,
  TPUV1_BAR2_REG_TN1_HBM_WRITE_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_NF_DESCRIPTOR_QUEUE,
  TPUV1_BAR2_REG_TN1_NF_DESCRIPTOR_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_CHIP_DEBUG_QUEUE,
  TPUV1_BAR2_REG_TN1_CHIP_DEBUG_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_TC_INFEED_QUEUE,
  TPUV1_BAR2_REG_TN1_TC_INFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_BC_INFEED_QUEUE,
  TPUV1_BAR2_REG_TN1_BC_INFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_TC_OUTFEED_QUEUE,
  TPUV1_BAR2_REG_TN1_TC_OUTFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_BC_OUTFEED_QUEUE,
  TPUV1_BAR2_REG_TN1_BC_OUTFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_BC_FSM_MICROCODE_QUEUE,
  TPUV1_BAR2_REG_TN1_FSM_MICROCODE_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_NF_OUTFEED_QUEUE,
  TPUV1_BAR2_REG_TN1_NF_OUTFEED_QUEUE_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_TN1_TC_HOST_0, TPUV1_BAR2_REG_TN1_TC_HOST_INT_INTVECCTL,
  PACK_0 },
 { TPUV1_INTERRUPT_TN1_TC_HOST_1, TPUV1_BAR2_REG_TN1_TC_HOST_INT_INTVECCTL,
  PACK_1 },
 { TPUV1_INTERRUPT_TN1_TC_HOST_2, TPUV1_BAR2_REG_TN1_TC_HOST_INT_INTVECCTL,
  PACK_2 },
 { TPUV1_INTERRUPT_TN1_TC_HOST_3, TPUV1_BAR2_REG_TN1_TC_HOST_INT_INTVECCTL,
  PACK_3 },
 { TPUV1_INTERRUPT_TN1_TC_HALTED, TPUV1_BAR2_REG_TN1_TC_HALTED_INTVECCTL,
  UNPACKED },
 { TPUV1_INTERRUPT_ERROR, TPUV1_BAR2_REG_MGT_ERROR_INTVECCTL, UNPACKED },
 { TPUV1_INTERRUPT_LINK, TPUV1_BAR2_REG_MGT_LINK_INTERRUPT_VECTOR, UNPACKED },
 { TPUV2_INTERRUPT_TN0_BC_HOST_0, TPUV2_BAR2_REG_TN0_BC_HOST_INT_INTVECCTL,
  PACK_0 },
 { TPUV2_INTERRUPT_TN0_BC_HOST_1, TPUV2_BAR2_REG_TN0_BC_HOST_INT_INTVECCTL,
  PACK_1 },
 { TPUV2_INTERRUPT_TN0_BC_HOST_2, TPUV2_BAR2_REG_TN0_BC_HOST_INT_INTVECCTL,
  PACK_2 },
 { TPUV2_INTERRUPT_TN0_BC_HOST_3, TPUV2_BAR2_REG_TN0_BC_HOST_INT_INTVECCTL,
  PACK_3 },
 { TPUV2_INTERRUPT_TN1_BC_HOST_0, TPUV2_BAR2_REG_TN1_BC_HOST_INT_INTVECCTL,
  PACK_0 },
 { TPUV2_INTERRUPT_TN1_BC_HOST_1, TPUV2_BAR2_REG_TN1_BC_HOST_INT_INTVECCTL,
  PACK_1 },
 { TPUV2_INTERRUPT_TN1_BC_HOST_2, TPUV2_BAR2_REG_TN1_BC_HOST_INT_INTVECCTL,
  PACK_2 },
 { TPUV2_INTERRUPT_TN1_BC_HOST_3, TPUV2_BAR2_REG_TN1_BC_HOST_INT_INTVECCTL,
  PACK_3 }
};
static struct gasket_driver_desc tpuv2_desc = {
 .name = TPU_COMMON_ACCEL_TYPE,
 .chip_model = "dfc",
 .chip_version = "1.0.0",
 .driver_version = TPUV2_DRIVER_VERSION,
 .legacy_support = 0,
 .legacy_major = 0,
 .legacy_minor = 0,
 .module = THIS_MODULE,
 .pci_id_table = tpuv2_pci_ids,
 .num_page_tables = TPUV1_NUM_TENSOR_NODES,
 .page_table_configs = tpuv1_page_table_configs,
 .bar_descriptions = {
  { TPUV1_LBUS_BAR_BYTES, VM_READ, TPUV1_LBUS_BAR_OFFSET,
   TPUV1_NUM_LBUS_RANGES, lbus_mappable_regions },
  GASKET_UNUSED_BAR,
  { TPUV1_TN_BAR_BYTES, (VM_WRITE | VM_READ), TPUV1_TN_BAR_OFFSET,
   TPUV1_NUM_TN_RANGES, tn_mappable_regions },
  GASKET_UNUSED_BAR, GASKET_UNUSED_BAR, GASKET_UNUSED_BAR
 },
 .legacy_interrupt_bar_index = TPUV1_TN_BAR_INDEX,
 .num_interrupts = TPUV2_INTERRUPT_COUNT,
 .legacy_interrupts = tpuv2_interrupts,
 .legacy_interrupt_pack_width = 7,
 .add_dev_cb = tpuv1_add_dev_cb,
 .remove_dev_cb = tpuv1_remove_dev_cb,
 .enable_dev_cb = NULL,
 .disable_dev_cb = NULL,
 .sysfs_setup_cb = tpuv1_sysfs_setup_cb,
 .sysfs_cleanup_cb = NULL,
 .device_open_cb = tpuv1_device_open_cb,
 .device_release_cb = NULL,
 .device_close_cb = tpuv1_device_cleanup,
 .get_mappable_regions_cb = tpuv1_get_mappable_regions_cb,
 .ioctl_handler_cb = tpuv1_ioctl,
 .device_status_cb = tpuv1_get_status,
 .hardware_revision_cb = NULL,
 .device_reset_cb = tpuv1_reset,
};
MODULE_DESCRIPTION("Google tpu_v2 driver");
MODULE_VERSION(TPUV2_DRIVER_VERSION);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joshua Lang <joshualang@google.com>");
MODULE_DEVICE_TABLE(pci, tpuv2_pci_ids);
module_init(tpuv2_init);
module_exit(tpuv2_exit);
int __init tpuv2_init(void)
{
 return gasket_register_device(&tpuv2_desc);
}
void tpuv2_exit(void)
{
 gasket_unregister_device(&tpuv2_desc);
}
